默认布局:菜单混合模多级菜单显示效果
混合模式(mixedBar)是最复杂的导航模式:左侧只显示一级菜单的图标,顶部显示当前一级菜单下的二级和三级菜单。本节重点讲解如何获取顶级菜单数据、如何通过 CSS 深度选择器定制混合模式下的菜单样式,以及如何在 useMenu 中扩展获取顶级菜单的工具方法。
混合模式的视觉结构
┌──┬──────────────────────┐
│ │ 二级 | 二级 | 二级 │ ← 顶部:当前一级菜单的子菜单
│01├──────────────────────┤
│02│ │
│03│ Content │ ← 左侧只显示一级菜单图标
│04│ │
│..│ │
└──┴──────────────────────┘
text
左侧的 Menu 组件只渲染顶级菜单项(图标模式),顶部的 Menu 组件渲染当前选中一级菜单的子菜单。
获取顶级菜单:getTopMenus
在 useMenu.ts 中新增一个工具方法,用于提取顶级菜单:
// src/components/menu/use-menu.ts
function getTopMenus(menus: AppRouteMenuItem[]): AppRouteMenuItem[] {
return menus
.filter((m) => !m.meta?.hideMenu)
.map((m) => ({
...m,
children: undefined, // 不包含子菜单
}))
}
typescript
在 Layout 组件中使用:
const topMenus = computed(() => getTopMenus(filteredMenus.value))
typescript
混合模式的样式定制
混合模式下左侧菜单只显示图标,需要通过深度选择器覆盖 Element Plus 的默认样式:
// 仅在混合模式下应用
.mixed-bar-mode {
:deep(.el-menu-item) {
padding: 0 !important;
justify-content: center;
.menu-title {
display: none; // 隐藏文字
}
}
:deep(.el-sub-menu__title) {
padding: 0 !important;
justify-content: center;
.menu-title {
display: none;
}
}
}
scss
条件绑定 class
只在 settings.mode === 'mixedBar' 时应用混合模式样式:
<Menu
:class="{ 'mixed-bar-mode': settings.mode === 'mixedBar' }"
:data="menus"
/>
vue
顶部二级菜单
顶部菜单区域使用另一个 Menu 组件,数据源是当前选中一级菜单的 children:
const currentTopMenu = computed(() => {
const active = topMenus.value.find(
(m) => m.meta?.key === activeTopKey.value
)
return active?.children ?? []
})
typescript
顶部菜单使用 mode="horizontal" 水平排列:
<Menu
mode="horizontal"
:data="currentTopMenu"
/>
vue
本节小结
- getTopMenus:从完整菜单数据中提取顶级菜单,移除 children 属性。
- 深度选择器:使用
:deep()覆盖 Element Plus 的默认样式,隐藏混合模式下的菜单文字。 - 条件样式:通过
:class绑定动态应用混合模式样式类。 - 顶部菜单:根据当前选中的一级菜单动态渲染对应的子菜单。
↑